import Taro from '@tarojs/taro'
import * as Utils from './index'

class Transform {
    static instance

    static getInstance() {
        if (this.instance instanceof this === false) {
            this.instance = new this()
        }
        return this.instance
    }

    size(s, scale = 750) {
        // 按照750px的设计稿尺寸换算成当前屏幕的尺寸
        return Taro.pxTransform((s * 750) / scale)
    }

    // 尺寸转换
    changeSize(styles = {}, scale = 750) {
        const newStyles = {}
        Object.keys(styles).forEach((key) => {
            newStyles[key] = styles[key]
            switch (key) {
                case 'width':
                case 'height':
                case 'top':
                case 'right':
                case 'bottom':
                case 'left':
                case 'margin':
                case 'marginTop':
                case 'marginRight':
                case 'marginBottom':
                case 'marginLeft':
                case 'marginHorizontal':
                case 'marginVertical':
                case 'padding':
                case 'paddingTop':
                case 'paddingRight':
                case 'paddingBottom':
                case 'paddingLeft':
                case 'paddingHorizontal':
                case 'paddingVertical':
                case 'fontSize':
                case 'borderWidth':
                case 'borderRadius':
                case 'shadowRadius':
                case 'minWidth':
                case 'minHeight':
                case 'maxWidth':
                case 'maxHeight':
                case 'lineHeight':
                    Utils.getType(styles[key]) === 'number' && (newStyles[key] = this.size(styles[key], scale))
                    break
                case 'shadowOffset':
                    if (Taro.getEnv() !== 'RN') {
                        Utils.getType(styles[key].width) === 'number' && (newStyles[key].width = this.size(styles[key].width, scale))
                        Utils.getType(styles[key].height) === 'number' && (newStyles[key].height = this.size(styles[key].height, scale))
                    }
                    break
                default:
                    break
            }
        })
        return newStyles
    }

    // RN样式转化
    styles(params = {}, scale = 375) {
        let styles = {}
        const transformStyle = {}
        switch (Utils.getType(params)) {
            case 'array':
                styles = Object.assign({}, ...params)
                break
            case 'object':
                styles = { ...params }
                break
            default:
                break
        }

        styles = this.changeSize(styles, scale)

        if (Taro.getEnv() !== 'RN') {
            const boxShadow = {}
            transformStyle.display = 'flex'
            transformStyle.flexShrink = 0
            transformStyle.flexDirection = 'column'
            if (Object.prototype.hasOwnProperty.call(styles, 'marginHorizontal')) {
                transformStyle.marginLeft = styles.marginLeft || styles.marginHorizontal
                transformStyle.marginRight = styles.marginRight || styles.marginHorizontal
            }
            if (Object.prototype.hasOwnProperty.call(styles, 'marginVertical')) {
                transformStyle.marginTop = styles.marginTop || styles.marginVertical
                transformStyle.marginBottom = styles.marginBottom || styles.marginVertical
            }

            if (Object.prototype.hasOwnProperty.call(styles, 'paddingHorizontal')) {
                transformStyle.paddingLeft = styles.paddingLeft || styles.paddingHorizontal
                transformStyle.paddingRight = styles.paddingRight || styles.paddingHorizontal
            }
            if (Object.prototype.hasOwnProperty.call(styles, 'paddingVertical')) {
                transformStyle.paddingTop = styles.paddingTop || styles.paddingVertical
                transformStyle.paddingBottom = styles.paddingBottom || styles.paddingVertical
            }
            delete styles.marginHorizontal
            delete styles.marginVertical
            delete styles.paddingHorizontal
            delete styles.paddingVertical
            Object.keys(styles).forEach((key) => {
                switch (key) {
                    case 'shadowOffset':
                        boxShadow.x = styles[key].width
                        boxShadow.y = styles[key].height
                        break
                    case 'shadowRadius':
                        boxShadow.r = styles[key]
                        break
                    case 'shadowColor':
                        boxShadow.c = styles[key]
                        break
                    case 'shadowOpacity':
                        boxShadow.o = styles[key]
                        break
                    case 'elevation':
                        break
                    case 'marginHorizontal':
                        transformStyle['margin-left'] = styles[key]
                        transformStyle['margin-right'] = styles[key]
                        break
                    case 'alignSelf':
                        transformStyle['margin-left'] = 'auto'
                        transformStyle['margin-right'] = 'auto'
                        break
                    case 'marginVertical':
                        transformStyle['margin-top'] = styles[key]
                        transformStyle['margin-bottom'] = styles[key]
                        break
                    case 'paddingHorizontal':
                        transformStyle['padding-left'] = styles[key]
                        transformStyle['padding-right'] = styles[key]
                        break
                    case 'paddingVertical':
                        transformStyle['padding-top'] = styles[key]
                        transformStyle['padding-bottom'] = styles[key]
                        break
                    case 'borderWidth':
                        transformStyle[key] = styles[key]
                        transformStyle.borderStyle = 'solid'
                        break
                    default:
                        transformStyle[key] = styles[key]
                        break
                }
            })
            if (boxShadow.c) {
                transformStyle['box-shadow'] = `${boxShadow.x || 0} 
          ${boxShadow.y || 0} 
          ${boxShadow.r || 0} 
          ${this.colorRgb(boxShadow.c, boxShadow.o)}`
            }
            return transformStyle
        }
        return styles
    }

    // RGB转换为16进制
    colorHex(color) {
        // RGB颜色值的正则
        const reg = /^(rgb|RGB)/
        if (reg.test(color)) {
            let strHex = '#'
            // 把RGB的3个数值变成数组
            const colorArr = color.replace(/(?:\(|\)|rgb|RGB)*/g, '').split(',')
            // 转成16进制
            for (let i = 0; i < colorArr.length; i++) {
                let hex = Number(colorArr[i]).toString(16)
                if (hex === '0') {
                    hex += hex
                }
                strHex += hex
            }
            return strHex
        }
        return String(color)
    }

    // 16进制转换为RGB
    colorRgb(color, opacity) {
        // 16进制颜色值的正则
        const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
        // 把颜色值变成小写
        let newColor = color.toLowerCase()
        if (reg.test(newColor)) {
            // 如果只有三位的值，需变成六位，如：#fff => #ffffff
            if (newColor.length === 4) {
                let colorNew = '#'
                for (let i = 1; i < 4; i += 1) {
                    colorNew += newColor.slice(i, i + 1).concat(newColor.slice(i, i + 1))
                }
                newColor = colorNew
            }
            // 处理六位的颜色值，转为RGB
            const colorChange = []
            for (let i = 1; i < 7; i += 2) {
                colorChange.push(parseInt(`0x${newColor.slice(i, i + 2)}`))
            }
            if (!Number.isNaN(parseFloat(opacity))) {
                colorChange.push(+opacity)
            }
            return `${(colorChange.length > 3 ? 'rgba(' : 'rgb(') + colorChange.join(',')})`
        }
        return newColor
    }

    // 日期格式化
    formatTime(date, format) {
        // eslint-disable-next-line eqeqeq
        date = new Date(date) == 'Invalid Date' ? new Date() : new Date(date)
        const defaultFormat = format || 'yyyy-MM-dd hh:mm:ss'
        const year = date.getFullYear()
        const month = date.getMonth() + 1
        const day = date.getDate()
        const hour = date.getHours()
        const minute = date.getMinutes()
        const second = date.getSeconds()
        const formatNumber = (n) => {
            n = n.toString()
            return n[1] ? n : `0${n}`
        }
        return defaultFormat
            .replace('yyyy', year)
            .replace('MM', formatNumber(month))
            .replace('dd', formatNumber(day))
            .replace('hh', formatNumber(hour))
            .replace('mm', formatNumber(minute))
            .replace('ss', formatNumber(second))
    }
}
export default Transform.getInstance()
